home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / library / __fstat.c < prev    next >
C/C++ Source or Header  |  1995-05-27  |  9KB  |  268 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
  20.  *
  21.  *  __fstat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:08  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  21:49:59  mw
  26.  *  "grp/oth-perms,
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36.  
  37. #if __GNUC__ != 2
  38. #define alloca __builtin_alloca
  39. #endif
  40.  
  41. #ifndef ACTION_EXAMINE_FH
  42. #define ACTION_EXAMINE_FH 1034
  43. #endif
  44.  
  45. #ifndef ST_LINKDIR
  46. #define ST_ROOT        1
  47. #define ST_USERDIR    2
  48. #define ST_SOFTLINK    3    /* looks like dir, but may point to a file! */
  49. #define ST_LINKDIR    4    /* hard link to dir */
  50. #define ST_FILE        -3    /* must be negative for FIB! */
  51. #define ST_LINKFILE    -4    /* hard link to file */
  52. #define ST_PIPEFILE    -5    /* for pipes that support ExamineFH */
  53. #endif
  54.  
  55. extern void *alloca ();
  56.  
  57. /************************************************************************/
  58. /*                                                                      */
  59. /*    fstat() function.                                                 */
  60. /*                                                                      */
  61. /************************************************************************/
  62.  
  63. int
  64. __fstat(struct file *f)
  65. {
  66.   long len, pos;
  67.   struct FileInfoBlock *fib;
  68.   struct InfoData *info;
  69.   int omask;
  70.  
  71.   omask = syscall (SYS_sigsetmask, ~0);
  72.   __get_file (f);
  73.  
  74.   /* take special care of NIL:, /dev/null and friends ;-) */
  75.   if (HANDLER_NIL(f))
  76.     {
  77.       f->f_stb.st_mode = S_IFCHR | 0777;
  78.       f->f_stb.st_nlink = 1;
  79.       f->f_stb.st_blksize = ix.ix_fs_buf_factor * 512;
  80.       f->f_stb.st_blocks = 0;
  81.       goto end;
  82.     }
  83.  
  84.   info = alloca (sizeof (*info) + 2);
  85.   info = LONG_ALIGN (info);
  86.   fib  = alloca (sizeof (*fib) + 2);
  87.   fib  = LONG_ALIGN (fib);
  88.     
  89.   __wait_packet (&f->f_sp);
  90.   /* reset the error field */
  91.   LastError (f) = 0;
  92.  
  93.   /* we now have two possibilities.. either the filesystem understands the
  94.    * new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
  95. /*  SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, CTOBPTR(f->f_fh), CTOBPTR(fib));*/
  96.   SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
  97.   __wait_packet (&f->f_sp);
  98.   if (LastResult(f))
  99.     {
  100.       int mode;
  101.  
  102.       f->f_stb.st_nlink = 1; /* always one link entry per file, unless... */
  103.       f->f_stb.st_amode = fib->fib_Protection;
  104.  
  105.       mode = 0;
  106.       if (!(fib->fib_Protection & FIBF_EXECUTE))
  107.         mode |= S_IXUSR;
  108.       if (!(fib->fib_Protection & FIBF_WRITE))
  109.         mode |= S_IWUSR;
  110.       if (!(fib->fib_Protection & FIBF_READ))
  111.         mode |= S_IRUSR;
  112. #ifdef FIBF_GRP_EXECUTE
  113.       /* FIBF_GRP_EXECUTE requires at least OS3 headers */
  114.       if (!(fib->fib_Protection & FIBF_GRP_EXECUTE))
  115.         mode |= S_IXGRP;
  116.       if (!(fib->fib_Protection & FIBF_GRP_WRITE))
  117.         mode |= S_IWGRP;
  118.       if (!(fib->fib_Protection & FIBF_GRP_READ))
  119.         mode |= S_IRGRP;
  120.       if (!(fib->fib_Protection & FIBF_OTR_EXECUTE))
  121.         mode |= S_IXOTH;
  122.       if (!(fib->fib_Protection & FIBF_OTR_WRITE))
  123.         mode |= S_IWOTH;
  124.       if (!(fib->fib_Protection & FIBF_OTR_READ))
  125.         mode |= S_IROTH;
  126. #endif
  127.  
  128.       switch (fib->fib_DirEntryType)
  129.         {
  130.         case ST_LINKDIR:
  131.           f->f_stb.st_nlink ++;  /* we never get more than a link count of two.. */
  132.         case ST_ROOT:
  133.         case ST_USERDIR:
  134.           mode |= S_IFDIR;
  135.           break;
  136.  
  137.         /* at the moment, we NEVER get this entry, since we can't get a lock
  138.          * on a symlink */
  139.         case ST_SOFTLINK:
  140.           mode |= S_IFLNK;
  141.           break;
  142.  
  143.     case ST_PIPEFILE:
  144.       /* don't use S_IFIFO, we don't have a mkfifo() call ! */
  145.       mode |= S_IFCHR;
  146.       break;
  147.  
  148.         case ST_LINKFILE:
  149.           f->f_stb.st_nlink ++;
  150.         case ST_FILE:
  151.         default:
  152.           mode |= S_IFREG;
  153.         }
  154.  
  155.       /* ARGLLLLL !!!
  156.          Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
  157.          don't know yet about ST_PIPEFILE. So console windows claim they're
  158.          plain files... Until this problem is fixed in a majority of
  159.          handlers, do an explicit SEEK here to find those fakers.. */
  160.       LastError(f) = 0;
  161.       SendPacket3(f,__rwport,ACTION_SEEK,f->f_fh->fh_Arg1,0,OFFSET_CURRENT);
  162.       __wait_packet (&f->f_sp);
  163.       if (LastError (f))
  164.         mode = (mode & ~S_IFREG) | S_IFCHR;
  165.  
  166.       f->f_stb.st_mode = mode;
  167.  
  168.       /* support for annotated attributes (cool name ;-)) */
  169.       if (! strncmp (fib->fib_Comment, "!SP!", 4))
  170.         {
  171.           int sp_mode, sp_addr;
  172.  
  173.           if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
  174.             f->f_stb.st_mode = sp_mode;
  175.         }
  176.   
  177.       /* some kind of a default-size for directories... */
  178.       f->f_stb.st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  179.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  180.       f->f_stb.st_dev = (dev_t)f->f_stb.st_handler; /* trunc to 16 bit */
  181.       f->f_stb.st_ino = fib->fib_DiskKey; 
  182.       f->f_stb.st_atime =
  183.       f->f_stb.st_ctime =
  184.       f->f_stb.st_mtime = (8*365+2)*24*3600 + /* offset to unix-timesystem */
  185.                   fib->fib_Date.ds_Days * 24 * 60 * 60 +
  186.                   fib->fib_Date.ds_Minute * 60 +
  187.                   fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  188.       /* in a try to count the blocks used for filemanagement, we add one for
  189.        * the fileheader. Note, that this is wrong for large files, where there
  190.        * are some extension-blocks as well */
  191.       f->f_stb.st_blocks = fib->fib_NumBlocks + 1;
  192.     }
  193.   else
  194.     {
  195.       /* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
  196.       /* seek to EOF */
  197.       SendPacket3 (f, __rwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
  198.       __wait_packet (&f->f_sp);
  199.       pos = LastResult (f);
  200.       if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
  201.         {
  202.           SendPacket3 (f, __rwport,ACTION_SEEK, f->f_fh->fh_Arg1, 
  203.                    pos, OFFSET_BEGINNING);
  204.           __wait_packet (&f->f_sp);
  205.           len = LastError (f) ? -1 : LastResult (f);
  206.         }
  207.       else
  208.         len = 0;
  209.  
  210.       bzero (&f->f_stb, sizeof(struct stat));
  211.  
  212.       f->f_stb.st_mode = ((len >= 0 && 
  213.                      /* !IsInteractive(CTOBPTR(f->f_fh)) */! f->f_fh->fh_Port)
  214.                      ? S_IFREG : S_IFCHR) | 0777;
  215.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  216.       /* the following is a limited try to support programs, that assume that
  217.        * st_dev is always valid */
  218.       f->f_stb.st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
  219.       /* yet another kludge.. if we call this with different descriptors, we
  220.        * should get different inode numbers.. grmpf.. */
  221.       f->f_stb.st_ino = (ino_t)~(long)(f->f_fh);
  222.       f->f_stb.st_nlink = 1; /* for now no problem.. 2.0... */
  223.       /* len could be -1, if the device doesn't allow seeking.. */
  224.       f->f_stb.st_size = len >= 0 ? len : 0;
  225.       f->f_stb.st_atime =  
  226.       f->f_stb.st_mtime =
  227.       f->f_stb.st_ctime = syscall (SYS_time, 0);
  228.     }
  229.  
  230.   /* try to find out block size of device, hey postman, it's packet-time
  231.    * again:-)) */
  232.   /* make sure, the packet is not in use anymore */
  233.   __wait_packet(&f->f_sp);
  234.  
  235.   /* clear the info-structure. Since this packet is used by the console
  236.    * handler to transmit the window pointer, it actually answers the
  237.    * request, but doesn't set the not used fields to 0.. this gives HUGE
  238.    * block lengths :-)) */
  239.   bzero (info, sizeof(*info));
  240.   SendPacket1(f,__rwport,ACTION_DISK_INFO,CTOBPTR(info));
  241.   __wait_packet(&f->f_sp);
  242.  
  243.   f->f_stb.st_blksize = 0;
  244.   if (LastResult (f) && info->id_BytesPerBlock)
  245.     {
  246.       f->f_stb.st_blksize = info->id_BytesPerBlock;
  247.       if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(f->f_stb.st_mode))
  248.     f->f_stb.st_blksize *= ix.ix_fs_buf_factor;
  249.       if (! f->f_stb.st_blocks) 
  250.     f->f_stb.st_blocks = ((f->f_stb.st_size + info->id_BytesPerBlock - 1) 
  251.                     / info->id_BytesPerBlock);
  252.     }
  253.  
  254.   if (! f->f_stb.st_blksize) 
  255.     {
  256.       f->f_stb.st_blksize = 512;
  257.       f->f_stb.st_blocks = (f->f_stb.st_size + 511) >> 9;
  258.     }
  259.  
  260. end:
  261.   /* reset error of packet. write() would fail if not */
  262.   LastResult(f) = 0;
  263.  
  264.   __release_file (f);
  265.   syscall (SYS_sigsetmask, omask);
  266.   return 0;
  267. }
  268.